﻿using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using Redmine.Laptop.API.Models;
using Redmine.Laptop.API.SearchCriteria;
using Redmine.Net.Api;
using RedmineTypes = Redmine.Net.Api.Types;

namespace Redmine.Laptop.API
{
    public class RedmineService
    {
        private readonly RedmineManager _redmineManager;

        public RedmineService(string host, string apiKey)
        {
            _redmineManager = new RedmineManager(host, apiKey, MimeFormat.json); 
        }

        public RedmineService(string host, string login, string password)
        {
            _redmineManager = new RedmineManager(host, login, password, MimeFormat.json);
        }

        /// <summary>
        /// Get all available projects
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Project> GetProjects()
        {
            return _redmineManager.GetTotalObjectList<RedmineTypes::Project>(null).Select(p => (Project)p);
        }

        /// <summary>
        /// Get all issue statuses
        /// </summary>
        /// <returns></returns>
        public IEnumerable<IssueStatus> GetIssueStatuses()
        {
            return _redmineManager.GetTotalObjectList<RedmineTypes::IssueStatus>(null).Select(i => (IssueStatus) i);
        }

        /// <summary>
        /// Get all users
        /// </summary>
        /// <returns></returns>
        public IEnumerable<User> GetUsers()
        {
            return GetUsers(new UserCriteria());
        }

        /// <summary>
        /// Get users by specified criteria
        /// </summary>
        /// <param name="criteria">User criteria</param>
        /// <returns></returns>
        public IEnumerable<User> GetUsers(UserCriteria criteria)
        {
            var parameters = new NameValueCollection();
            
            if (criteria.GroupID.HasValue)
                parameters.Add("group_id", criteria.GroupID.Value.ToString());

            return _redmineManager.GetTotalObjectList<RedmineTypes::User>(parameters).Select(u => (User) u);
        }

        /// <summary>
        /// Get issues by specified criteria
        /// </summary>
        /// <param name="criteria">Issue criteria</param>
        /// <returns></returns>
        public IEnumerable<Issue> GetIssues(IssueCriteria criteria)
        {
            var parameters = new NameValueCollection();
            
            if (criteria.AssignedUserID.HasValue)
                parameters.Add("assigned_to_id", criteria.AssignedUserID.Value.ToString());
            if (criteria.AuthorID.HasValue)
                parameters.Add("author_id", criteria.AuthorID.Value.ToString());
            if (criteria.ProjectID.HasValue)
                parameters.Add("project_id", criteria.ProjectID.Value.ToString());

            return _redmineManager.GetTotalObjectList<RedmineTypes::Issue>(parameters).Select(i => (Issue) i);
        }

        /// <summary>
        /// Get time entries by specified criteria
        /// </summary>
        /// <param name="criteria">Time entry criteria</param>
        /// <returns></returns>
        public IEnumerable<TimeEntry> GetTimeEntries(TimeEntryCriteria criteria)
        {
            var parameters = new NameValueCollection();

            if (criteria.ProjectID.HasValue)
                parameters.Add("project_id", criteria.ProjectID.Value.ToString());
            if (criteria.UserID.HasValue)
                parameters.Add("assigned_to_id", criteria.UserID.Value.ToString());
            if (criteria.FromDate.HasValue)    
                parameters.Add("from", criteria.FromDate.Value.ToString("yyyy-MM-dd"));
            if (criteria.ThruDate.HasValue)    
                parameters.Add("to", criteria.ThruDate.Value.ToString("yyyy-MM-dd"));
            
            return _redmineManager.GetTotalObjectList<RedmineTypes::TimeEntry>(parameters).Select(i => (TimeEntry)i);
        }
    } 
}
